<template>
    <div
        class="keyboard-container"
        id="keyboardarea"
        @pointerdown="handleKeyboardEvent"
        @pointerup="handleKeyboardEvent"
        @pointercancel="handleKeyboardEvent"
    >
        <div class="keyboard-area">
            <div
                class="keyboard-row"
                v-for="(keyrow, index) in keyMap.map[keyMap.bd.Type]"
                :key="'row' + index"
            >
                <template
                    v-if="
                        keyMap.bd.Zh && keyMap.bd.Type === 'Font' && index === 0
                    "
                >
                    <div class="keyboard-zh">
                        <div class="zh-keys" v-if="keyMap.bd.zhs">
                            {{ keyMap.bd.zhs }}
                        </div>
                        <div class="zh-list-area">
                            <div
                                class="zh-list"
                                v-if="keyMap.bd?.zharr?.length"
                            >
                                <div
                                    v-for="(zh, index) in keyMap.bd.zharr"
                                    :key="'zh' + index"
                                    class="askey zh-li"
                                    :data-key="zh"
                                >
                                    {{ zh }}
                                </div>
                            </div>
                        </div>
                    </div>
                </template>
                <template v-else>
                    <div
                        class="keyboard-item"
                        v-for="keyitem in keyrow"
                        :key="keyitem[0]"
                        :style="{ width: `${keyitem[1]}%` }"
                    >
                        <button
                            v-if="keyitem[4]"
                            :class="`askey keyboard-key${
                                keyitem[3] ? ' key-bg' : ''
                            }${keyMap.bd[keyitem[4]] ? ' active' : ''}`"
                            :data-key="keyitem[0]"
                        >
                            {{
                                keyitem[5]
                                    ? keyMap.bd[keyitem[5]]
                                    : keyitem[2] || keyitem[0]
                            }}
                        </button>

                        <button
                            v-else-if="keyitem[0] === 'Drag'"
                            class="keyboard-key key-bg"
                            v-dragzoom="{
                                ujt,
                                pos: $global.keyboard.areastyle,
                                domarea: 'askeyboardarea',
                                dommask: 'askeyboardmask',
                            }"
                        >
                            {{ keyitem[2] || keyitem[0] }}
                        </button>

                        <button
                            v-else
                            :class="`askey keyboard-key${
                                keyitem[3] ? ' key-bg' : ''
                            }`"
                            :data-key="keyitem[0]"
                        >
                            {{
                                keyitem[5]
                                    ? keyMap.bd[keyitem[5]]
                                    : keyitem[2] ||
                                      (keyMap.bd.Shift
                                          ? keyitem[0].toUpperCase()
                                          : keyitem[0])
                            }}
                        </button>
                    </div>
                </template>
            </div>
        </div>
    </div>
</template>

<script setup lang="ts">
import { nextTick, watch, reactive } from 'vue';

interface Props {
    ujt: any;
}

const props = defineProps<Props>();

const { $dbwork, $model, $fn, $global } = props.ujt;

const keyMap: any = reactive({
    bd: {
        Shift: false,
        Ctrl: false,
        Type: 'Font',
        Zh: false,
        zhs: '',
        zharr: [],
        pos: 0,
    },
    ge: '8px',
    gs: '5px',
    map: {
        Font: [
            [
                ['1', 10],
                ['2', 10],
                ['3', 10],
                ['4', 10],
                ['5', 10],
                ['6', 10],
                ['7', 10],
                ['8', 10],
                ['9', 10],
                ['0', 10],
            ],
            [
                ['q', 10],
                ['w', 10],
                ['e', 10],
                ['r', 10],
                ['t', 10],
                ['y', 10],
                ['u', 10],
                ['i', 10],
                ['o', 10],
                ['p', 10],
            ],
            [
                ['a', 10],
                ['s', 10],
                ['d', 10],
                ['f', 10],
                ['g', 10],
                ['h', 10],
                ['j', 10],
                ['k', 10],
                ['l', 10],
                ['Backspace', 10, '⌫', 1],
            ],
            [
                ['z', 10],
                ['x', 10],
                ['c', 10],
                ['v', 10],
                ['b', 10],
                ['n', 10],
                ['m', 10],
                ['-', 10],
                ['.', 10],
                ['Enter', 10, '↵', 1],
            ],
            [
                ['Shift', 10, '', 1, 'Shift'],
                ['Ctrl', 10, '', 1, 'Ctrl'],
                ['Zh', 10, '中文', 1, 'Zh'],
                [' ', 40, 'Space', 1],
                ['Char', 10, '', 1, '', 'Type'],
                ['Hide', 10, '', 1],
                ['Drag', 10, '☩', 1],
            ],
        ],
        Char: [
            [
                ['!', 10],
                ['@', 10],
                ['#', 10],
                ['$', 10],
                ['%', 10],
                ['^', 10],
                ['&', 10],
                ['*', 10],
                ['(', 10],
                [')', 10],
            ],
            [
                ['{', 10],
                ['}', 10],
                ['[', 10],
                [']', 10],
                ['<', 10],
                ['>', 10],
                ['|', 10],
                ['\\', 10],
                ['/', 10],
                ['=', 10],
            ],
            [
                [':', 10],
                [';', 10],
                [',', 10],
                ["'", 10],
                ['"', 10],
                ['`', 10],
                ['~', 10],
                ['+', 10],
                ['_', 10],
                ['Backspace', 10, '⌫', 1],
            ],
            [
                ['{}', 10],
                ['()', 10],
                ['[]', 10],
                ['<>', 10],
                ['>=', 10],
                ['<=', 10],
                ['?', 10],
                ['-', 10],
                ['.', 10],
                ['Enter', 10, '↵', 1],
            ],
            [
                ['Shift', 10, '', 1, 'Shift'],
                ['Ctrl', 10, '', 1, 'Ctrl'],
                ['Zh', 10, '中文', 1, 'Zh'],
                [' ', 40, 'Space', 1],
                ['Char', 10, '', 1, '', 'Type'],
                ['Hide', 10, '', 1],
                ['Drag', 10, '☩', 1],
            ],
        ],
    },
});

watch(
    () => $global.keyboard.isshow,
    (newVal, oldVal) => {
        if (newVal && newVal !== oldVal) {
            show();
        }
    }
);

const updateCursorPosition = () => {
    if ($global.keyboard.params?.el) {
        keyMap.bd.pos = $global.keyboard.params.el.selectionStart || 0;
    }
};

const show = () => {
    nextTick(() => {
        setTimeout(() => {
            updateCursorPosition();
        }, 10);
    });
};

const hide = () => {
    $global.keyboard.params?.ot?.fndscb();
    $global.keyboard.isshow = 0;
    $global.keyboard.params = null;
};

const changemap = () => {
    const keyMapArr: any = Object.keys(keyMap.map);
    keyMap.bd.Type =
        keyMap.bd.Type === keyMapArr[0] ? keyMapArr[1] : keyMapArr[0];
};
const updateInputValue = (
    elDom: HTMLInputElement | HTMLTextAreaElement,
    newValue: string,
    newCursorPos: number,
    char: any = null,
    onsuggest: any = null
) => {
    // 检查是否是 Monaco Editor 实例
    if ($global.keyboard.params.type === 'monaco') {
        if ($global.keyboard.opt?.backText && char === 0) {
            $global.keyboard.opt?.backText();
            return;
        } else if ($global.keyboard.opt?.insertText && char != null) {
            // 如果有选中值，这里先删除掉，再插入新的字符
            if ($global.keyboard.opt?.backText) {
                const {
                    endColumn,
                    endLineNumber,
                    startColumn,
                    startLineNumber,
                } = $model.lua.editor.getSelection();
                if (
                    endColumn !== startColumn ||
                    endLineNumber !== startLineNumber
                ) {
                    $global.keyboard.opt?.backText();
                }
            }
            $global.keyboard.opt?.insertText(char, onsuggest);
            return;
        }
    }
    elDom.value = newValue;
    keyMap.bd.pos = newCursorPos;
    elDom.dispatchEvent(new Event('input', { bubbles: true }));
    // nextTick(() => {
    // console.log(666.009, elDom.type);
    try {
        elDom.focus();
        elDom.setSelectionRange(newCursorPos, newCursorPos);
    } catch (e) {
        $global.keyboard.params?.ot?.fnnumcb?.();
        //     elDom.blur();
    }
    // });
};

const handleInsertChar = (
    key: string,
    elDom: any,
    elVal: any,
    startPos: any,
    endPos: any,
    char: any = null,
    onsuggest: any = 0
) => {
    char = char || (keyMap.bd.Shift ? key.toUpperCase() : key);
    const newValue = elVal.slice(0, startPos) + char + elVal.slice(endPos);
    updateInputValue(elDom, newValue, startPos + char.length, char, onsuggest);
    elDom.focus();
    return newValue;
};

const handleKeyPress = async (key: string) => {
    const elDom = $global.keyboard.params?.el;
    if (!elDom) {
        return;
    }
    const elVal = elDom.value;
    let startPos, endPos;
    // if ($global.keyboard.params.type === 'monaco') {
    //     const { selectionStart, selectionEnd } =
    //         $model.lua.editor.getSelection();
    //     startPos = selectionStart;
    //     endPos = selectionEnd;
    //     console.log(666.333,startPos,endPos)
    // } else {
    startPos = elDom.selectionStart!;
    endPos = elDom.selectionEnd!;
    // }
    if (startPos == null) {
        startPos = elVal.length;
        endPos = elVal.length;
    }
    // console.log(666.112, key, elVal, elDom.selectionStart, startPos, endPos);

    switch (key) {
        case 'Backspace':
            // if (startPos > 0) {
            const deleteStart = startPos === endPos ? startPos - 1 : startPos;
            const newValue = elVal.slice(0, deleteStart) + elVal.slice(endPos);
            updateInputValue(elDom, newValue, deleteStart, 0);
            // }
            break;
        case 'Enter':
            handleInsertChar(key, elDom, elVal, startPos, endPos, '\n');
            break;
        case 'Shift':
            keyMap.bd.Shift = !keyMap.bd.Shift;
            break;
        case 'Ctrl':
            keyMap.bd.Ctrl = !keyMap.bd.Ctrl;
            break;
        case 'Zh':
            keyMap.bd.Zh = !keyMap.bd.Zh;
            break;
        case 'Char':
            changemap();
            break;
        case 'Hide':
            hide();
            break;
        case 'Drag':
            break;
        case ' ':
            if (keyMap.bd.Ctrl) {
                $global.keyboard.areastyle = {};
                keyMap.bd.Shift = false;
                keyMap.bd.Ctrl = false;
            } else {
                handleInsertChar(key, elDom, elVal, startPos, endPos);
            }
            break;
        case 'x':
            if (keyMap.bd.Ctrl) {
                try {
                    if (
                        $global.keyboard.params.type === 'monaco' &&
                        $global.keyboard.opt?.copyText &&
                        $global.keyboard.opt?.backText
                    ) {
                        $global.keyboard.opt?.copyText();
                        $global.keyboard.opt?.backText();
                        return;
                    }
                    await $fn.As.copyToClipboard(elVal.slice(startPos, endPos));
                } catch (err) {
                    console.error('copy fail: ', err);
                }
            } else {
                handleInsertChar(key, elDom, elVal, startPos, endPos);
            }
            break;
        case 'c':
            if (keyMap.bd.Ctrl) {
                try {
                    if (
                        $global.keyboard.params.type === 'monaco' &&
                        $global.keyboard.opt?.copyText
                    ) {
                        $global.keyboard.opt?.copyText();
                        return;
                    }
                    await $fn.As.copyToClipboard(elVal.slice(startPos, endPos));
                } catch (err) {
                    console.error('copy fail: ', err);
                }
            } else {
                handleInsertChar(key, elDom, elVal, startPos, endPos);
            }
            break;
        case 'v':
            if (keyMap.bd.Ctrl) {
                try {
                    if (
                        $global.keyboard.params.type === 'monaco' &&
                        $global.keyboard.opt?.pasteText
                    ) {
                        $global.keyboard.opt?.pasteText();
                        return;
                    }
                    const pastedText = await $fn.As.readFromClipboard();
                    handleInsertChar(
                        key,
                        elDom,
                        elVal,
                        startPos,
                        endPos,
                        pastedText
                    );
                } catch (err) {
                    console.error('paste fail: ', err);
                }
            } else {
                handleInsertChar(key, elDom, elVal, startPos, endPos);
            }
            break;
        default:
            // 判断字符是否为数字输入框
            if ($global.keyboard.params.ot.isnumber && !/[0-9.-]/.test(key)) {
                return;
            }
            handleInsertChar(
                key,
                elDom,
                elVal,
                startPos,
                endPos,
                null,
                $global.keyboard.params.type === 'monaco' &&
                    $global.keyboard.opt?.pasteText
                    ? 1
                    : 0
            );
            break;
    }
};
const mockDict = {
    ni: '你泥呢尼拟逆匿腻妮霓倪匿伲坭猊怩滠昵旎祢慝睨铌鲵',
    hao: '好号毫豪耗浩郝壕嚎皓嚎濠灏昊颢蚝',
    zhong: '中种重众钟忠终肿仲盅衷踵冢锺螽舂舯',
    zhou: '周州舟昼皱骤粥轴肘帚咒宙绉啁诹荮鬻纣胄碡籀舳酎鲷',
    gun: '滚棍辊丨衮绲磙鲧',
    guo: '国过果锅郭裹馘蠃埚掴呙囗帼崞猓椁虢锞聒蜮蜾蝈',
    ha: '哈蛤',
    li: '里离力理利立丽历例礼李粒梨璃黎励莉荔吏栗丽厉励砾历利傈例俐痢立粒沥隶力璃哩俪俚郦坜苈莅蓠藜捩呖唳喱猁溧澧逦娌嫠骊缡珞枥栎轹戾砺詈罹锂鹂疠疬蛎蜊蠡笠篥粝醴跞雳鲡鳢黧',
    lian: '连联练脸链恋莲镰廉怜涟帘敛脸链恋炼练挛蔹奁潋濂娈琏楝殓臁膦裢蠊鲢',
    liang: '两量良亮梁凉粮辆晾谅墚椋踉靓魉',
};
const getZhArr = (zhs: string) => {
    const matched = [];
    for (const [pinyin, words] of Object.entries(mockDict)) {
        if (pinyin.startsWith(zhs)) {
            matched.push(...words);
        }
    }
    return matched;
};
const pressKeyWork = (key: string, target: any) => {
    let iszh = false;
    if (keyMap.bd.Zh) {
        if (key === 'Backspace') {
            if (keyMap.bd.zhs) {
                keyMap.bd.zhs = keyMap.bd.zhs.slice(0, -1);
                keyMap.bd.zharr = getZhArr(keyMap.bd.zhs);
                iszh = true;
            }
            if (!keyMap.bd.zhs) {
                keyMap.bd.zharr = [];
            }
        } else if ([' ', 'Enter'].includes(key)) {
            if (keyMap.bd.zharr?.length) {
                keyMap.bd.zhs = '';
                key = keyMap.bd.zharr[0];
                keyMap.bd.zharr = [];
            }
        } else if ('qwertyuiopasdfghjklzxcvbnm'.includes(key)) {
            keyMap.bd.zhs += key;
            keyMap.bd.zharr = getZhArr(keyMap.bd.zhs);
            iszh = true;
        } else {
            if (keyMap.bd.zhs) {
                keyMap.bd.zhs = '';
            }
            if (keyMap.bd.zharr?.length) {
                if (!target.classList.contains('zh-li')) {
                    key = keyMap.bd.zharr[0] + key;
                }
                keyMap.bd.zharr = [];
            }
        }
    }
    !iszh && handleKeyPress(key);
};
const handleKeyboardEvent = (event: PointerEvent) => {
    const target = event.target as HTMLElement;
    if (!target.classList.contains('askey')) return;

    const key = target.dataset.key;
    if (!key) return;

    event.preventDefault();
    event.stopPropagation();
    let pressZh = target.classList.contains('zh-li');
    switch (event.type) {
        case 'pointerdown':
            !pressZh && pressKeyWork(key, target);
            break;
        case 'pointerup':
            // 可添加额外逻辑
            pressZh && pressKeyWork(key, target);
            break;
        case 'pointercancel':
            // 可添加额外逻辑
            break;
    }
};
</script>

<style scoped lang="scss">
.keyboard-container {
    width: 100%;
    height: 100%;
    user-select: none;
    -webkit-user-select: none;
    display: flex;
    justify-content: center;
    align-items: center;
    flex-direction: column;

    .keyboard-area {
        width: 98%;
        height: 98%;
        margin: 1%;
        display: flex;
        justify-content: center;
        align-items: center;
        flex-direction: column;
        .keyboard-zh,
        .keyboard-key {
            font-size: var(--fs3);
            margin: 0;
            padding: 0;
            border: none;
            border-radius: 1%;
            background-color: var(--ch0);
            box-shadow: 0 v-bind('keyMap.gs') v-bind('keyMap.gs')
                rgba(0, 0, 0, 0.1);
            text-shadow: 0 v-bind('keyMap.gs') v-bind('keyMap.gs')
                rgba(0, 0, 0, 0.1);
            touch-action: manipulation;
            overflow: hidden;
            white-space: nowrap;
            user-select: none;
            -webkit-user-select: none;
            -webkit-touch-callout: none;
            -webkit-tap-highlight-color: transparent;
        }
        .keyboard-key {
            width: calc(100% - v-bind('keyMap.ge'));
            height: calc(100% - v-bind('keyMap.ge'));
            cursor: pointer;
        }

        .keyboard-row {
            display: flex;
            justify-content: center;
            flex-wrap: nowrap;
            width: 100%;
            height: 20%;
            .keyboard-item {
                display: flex;
                justify-content: center;
                align-items: center;

                .keyboard-key:hover {
                    background: var(--ch2);
                }

                .keyboard-key:active,
                .keyboard-key.active {
                    background: var(--cm2);
                    transform: scale(0.9);
                }
                .key-bg {
                    background: var(--ch2);
                }
            }
        }

        .key-special {
            background: var(--ch2);
        }

        .key-space {
            width: 50%;
        }

        .key-drag {
            cursor: move;
            background: var(--ch2);
        }
    }

    .keyboard-zh {
        cursor: default !important;
        width: calc(100% - v-bind('keyMap.ge'));
        display: flex;
        justify-content: center;
        align-items: center;
        .zh-keys {
            background-color: var(--ch2);
            border-radius: 0 10px 10px 0;
            padding: 3px 12px 3px 8px;
            width: auto;
            display: inline-flex;
            align-items: center;
        }
        .zh-list-area {
            flex-grow: 1;
            // background-color: rgb(238, 253, 206);
            display: inline-block;
            .zh-list {
                align-items: center;
                display: flex;
                flex-wrap: nowrap;
            }
            .zh-li {
                display: inline-flex;
                padding: 0 12px;
                cursor: pointer;
            }
        }
        /* 基础容器样式 */
        .zh-list-area {
            overflow-y: auto;
            scrollbar-width: none; /* Firefox兼容 */
            -ms-overflow-style: none; /* IE/Edge兼容 */
        }

        /* WebKit滚动条完全隐藏 */
        .zh-list-area::-webkit-scrollbar {
            width: 0;
            height: 0;
            background: transparent;
        }

        /* 悬停时显示细滚动条 */
        .zh-list-area:hover::-webkit-scrollbar {
            width: 6px;
            height: 6px;
        }

        /* 滚动条滑块悬停效果 */
        .zh-list-area:hover::-webkit-scrollbar-thumb {
            background: rgba(0, 0, 0, 0.2);
            border-radius: 3px;
            transition: background 0.3s ease;
        }

        /* 滚动条轨道 */
        .zh-list-area:hover::-webkit-scrollbar-track {
            background: rgba(0, 0, 0, 0.05);
        }
    }
}
</style>
